home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / print.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  9KB  |  422 lines

  1. /* -*- mode: C; mode: fold; -*- */
  2. /* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
  3.  *
  4.  * This file is part of slrn.
  5.  *
  6.  * Slrn is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  * 
  11.  * Slrn is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * for more details.
  15.  * 
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with Slrn; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, 59 Temple Place - Suite 330, 
  19.  * Boston, MA  02111-1307, USA.
  20.  */
  21.  
  22. #include "config.h"
  23. #include "slrnfeat.h"
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. #ifdef __WIN32__
  29. # include <windows.h>
  30. #endif
  31.  
  32. #ifdef HAVE_STDLIB_H
  33. # include <stdlib.h>
  34. #endif
  35. #ifdef HAVE_UNISTD_H
  36. # include <unistd.h>
  37. #endif
  38.  
  39. #include "print.h"
  40. #include "misc.h"
  41. #include "util.h"
  42. #include "ttymsg.h"
  43.  
  44. char *Slrn_Printer_Name;
  45.  
  46. /* I am using prefixes such as popen_ for the benefit of those without a 
  47.  * folding editor.
  48.  */
  49. #ifdef USE_NOTEPAD_PRINT_CODE
  50. # define np_open_printer slrn_open_printer
  51. # define np_close_printer slrn_close_printer
  52. # define np_write_to_printer write_to_printer
  53. # ifdef __WIN32__
  54. #  define NOTEPAD_PRINT_CMD    "start /m notepad /p %s"
  55. # else
  56. #  ifdef VMS
  57. #   define NOTEPAD_PRINT_CMD    "PRINT/QUEUE=SYS$PRINT %s"
  58. #  else
  59. #   define NOTEPAD_PRINT_CMD    "lpr %s"
  60. #  endif
  61. # endif
  62. #else
  63. # ifdef __WIN32__
  64. #  define USE_WIN32_PRINT_CODE    1
  65. #  define win32_open_printer slrn_open_printer
  66. #  define win32_close_printer slrn_close_printer
  67. #  define win32_write_to_printer write_to_printer
  68. # else
  69. #  ifdef __unix__
  70. #   define USE_POPEN_PRINT_CODE    1
  71. #   define popen_open_printer slrn_open_printer
  72. #   define popen_close_printer slrn_close_printer
  73. #   define popen_write_to_printer write_to_printer
  74. #  else
  75. #   define USE_DUMMY_PRINT_CODE    1
  76. #   define dummy_open_printer slrn_open_printer
  77. #   define dummy_close_printer slrn_close_printer
  78. #   define dummy_write_to_printer write_to_printer
  79. #  endif
  80. # endif
  81. #endif
  82.  
  83.  
  84. #ifdef USE_WIN32_PRINT_CODE /*{{{*/
  85.  
  86. # ifdef HAVE_WINSPOOL_H
  87. #  include <winspool.h>
  88. # else
  89. extern WINBOOL WINAPI OpenPrinterA(LPTSTR, LPHANDLE, LPVOID);
  90. extern WINBOOL WINAPI ClosePrinter(HANDLE);
  91. extern DWORD WINAPI StartDocPrinterA(HANDLE, DWORD, LPBYTE);
  92. extern WINBOOL WINAPI EndDocPrinter(HANDLE);
  93. extern WINBOOL WINAPI StartPagePrinter(HANDLE);
  94. extern WINBOOL WINAPI EndPagePrinter(HANDLE);
  95. extern WINBOOL WINAPI WritePrinter(HANDLE, LPVOID, DWORD, LPDWORD);
  96. # endif
  97.  
  98. struct _Slrn_Print_Type
  99. {
  100.    int error_status;
  101.    HANDLE h;
  102. };
  103.  
  104. int win32_close_printer (Slrn_Print_Type *p)
  105. {
  106.    if ((p == NULL)
  107.        || (p->h == INVALID_HANDLE_VALUE))
  108.      return 0;
  109.    
  110.    EndDocPrinter (p->h);
  111.    ClosePrinter (p->h);
  112.    slrn_free ((char *) p);
  113.    return 0;
  114. }
  115.  
  116. Slrn_Print_Type *win32_open_printer (void)
  117. {
  118.    char printer_name_buf [256];
  119.    HANDLE h;
  120.    static DOC_INFO_1 doc_info = 
  121.      {
  122.     "slrn-print-file",           /* name of the document */
  123.     NULL,                   /* name of output file to use */
  124.     "RAW"                   /* data type */
  125.      };
  126.    Slrn_Print_Type *p;
  127.    char *printer_name;
  128.  
  129.    if (NULL == (p = (Slrn_Print_Type *) SLmalloc (sizeof (Slrn_Print_Type))))
  130.      return NULL;
  131.    
  132.    memset ((char *) p, 0, sizeof(Slrn_Print_Type));
  133.  
  134.    if (NULL == (printer_name = Slrn_Printer_Name))
  135.      {
  136.     (void) GetProfileString("windows", "device", "LPT1,,", printer_name_buf, sizeof(printer_name_buf));
  137.     printer_name = slrn_strchr (printer_name_buf, ',');
  138.     if (NULL != printer_name)
  139.       *printer_name = 0;
  140.     
  141.     printer_name = printer_name_buf;
  142.      }
  143.    
  144.    if (FALSE == OpenPrinterA (printer_name, &h, NULL))
  145.      {
  146.     slrn_error ("OpenPrinterA failed: %d", GetLastError ());
  147.     slrn_free ((char *) p);
  148.     return NULL;
  149.      }
  150.    
  151.    
  152.    if (FALSE == StartDocPrinterA (h, 1, (unsigned char *) &doc_info))
  153.      {
  154.     slrn_error ("StartDocPrinterA failed: %d", GetLastError ());
  155.     ClosePrinter (h);
  156.     slrn_free ((char *) p);
  157.     return NULL;
  158.      }
  159.    
  160.    p->h = h;
  161.    return p;
  162. }
  163.  
  164. static int win32_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len)
  165. {
  166.    DWORD nlen;
  167.    
  168.    if ((p == NULL) || (p->h == INVALID_HANDLE_VALUE) || (p->error_status != 0))
  169.      return -1;
  170.  
  171.    if (FALSE == WritePrinter (p->h, buf, len, &nlen))
  172.      {
  173.     p->error_status = 1;
  174.     slrn_error ("Write to printer failed: %d", GetLastError ());
  175.     return -1;
  176.      }
  177.    
  178.    return 0;
  179. }
  180.  
  181. /*}}}*/
  182. #endif                       /* USE_WIN32_PRINT_CODE */
  183.  
  184. #ifdef USE_NOTEPAD_PRINT_CODE /*{{{*/
  185.  
  186. struct _Slrn_Print_Type
  187. {
  188.    int error_status;
  189.    FILE *fp;
  190.    char file [SLRN_MAX_PATH_LEN];
  191. };
  192.  
  193. int np_close_printer (Slrn_Print_Type *p)
  194. {
  195.    char cmd [256 + SLRN_MAX_PATH_LEN];
  196.  
  197.    if ((p == NULL) || (p->fp == NULL))
  198.      return 0;
  199.    
  200.    (void) slrn_fclose (p->fp);
  201.    sprintf (cmd, NOTEPAD_PRINT_CMD, p->file);
  202.    slrn_posix_system (cmd, 1);
  203.    (void) slrn_delete_file (p->file);
  204.    
  205.    slrn_free ((char *) p);
  206.    return 0;
  207. }
  208.  
  209. Slrn_Print_Type *np_open_printer (void)
  210. {
  211.    Slrn_Print_Type *p;
  212.  
  213.    if (NULL == (p = (Slrn_Print_Type *) SLmalloc (sizeof (Slrn_Print_Type))))
  214.      return NULL;
  215.    
  216.    memset ((char *) p, 0, sizeof(Slrn_Print_Type));
  217.  
  218.    if (NULL == (p->fp = slrn_open_tmpfile (p->file, "w")))
  219.      {
  220.     slrn_error ("Failed to open tmp file");
  221.     slrn_free ((char *) p);
  222.     return NULL;
  223.      }
  224.  
  225.    return p;
  226. }
  227.  
  228. static int np_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len)
  229. {
  230.    if ((p == NULL) || (p->fp == NULL) || (p->error_status))
  231.      return -1;
  232.  
  233.    if (len != fwrite (buf, 1, len, p->fp))
  234.      {
  235.     p->error_status = 1;
  236.     slrn_error ("Write to printer failed");
  237.     return -1;
  238.      }
  239.  
  240.    return 0;
  241. }
  242.  
  243. /*}}}*/
  244. #endif
  245.  
  246. #ifdef USE_POPEN_PRINT_CODE /*{{{*/
  247. struct _Slrn_Print_Type
  248. {
  249.    int error_status;
  250.    FILE *fp;
  251. };
  252.  
  253. int popen_close_printer (Slrn_Print_Type *p)
  254. {
  255.    int code;
  256.  
  257.    if ((p == NULL) || (p->fp == NULL))
  258.      return 0;
  259.    
  260.    code = _slrn_pclose (p->fp);
  261.  
  262.    slrn_free ((char *) p);
  263.  
  264.    if (code == 0) return 0;
  265.    
  266.    slrn_error ("Printer process returned error code %d", code);
  267.    return -1;
  268. }
  269.  
  270. Slrn_Print_Type *popen_open_printer (void)
  271. {
  272.    char *print_cmd;
  273.    Slrn_Print_Type *p;
  274.    char print_cmd_buf[1024];
  275.  
  276.    if (NULL == (print_cmd = Slrn_Printer_Name))
  277.      {
  278.     print_cmd = getenv ("PRINTER");
  279.     if (print_cmd == NULL) print_cmd = "";
  280.     sprintf (print_cmd_buf, "lpr -P%s", print_cmd);
  281.     print_cmd = print_cmd_buf;
  282.      }
  283.  
  284.    if (NULL == (p = (Slrn_Print_Type *) SLmalloc (sizeof (Slrn_Print_Type))))
  285.      return NULL;
  286.    
  287.    memset ((char *) p, 0, sizeof(Slrn_Print_Type));
  288.  
  289.    if (NULL == (p->fp = popen (print_cmd, "w")))
  290.      {
  291.     slrn_error ("Failed to open process %s", print_cmd);
  292.     popen_close_printer (p);
  293.     return NULL;
  294.      }
  295.    
  296.    return p;
  297. }
  298.  
  299. static int popen_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len)
  300. {
  301.    if ((p == NULL) || (p->fp == NULL) || (p->error_status))
  302.      return -1;
  303.  
  304.    if (len != fwrite (buf, 1, len, p->fp))
  305.      {
  306.     p->error_status = 1;
  307.     slrn_error ("Error writing to print process");
  308.     return -1;
  309.      }
  310.    
  311.    return 0;
  312. }
  313.  
  314. /*}}}*/
  315. #endif                       /* USE_POPEN_PRINT_CODE */
  316.  
  317. #ifdef USE_DUMMY_PRINT_CODE /*{{{*/
  318. struct _Slrn_Print_Type
  319. {
  320.    int error_status;
  321. };
  322.  
  323. Slrn_Print_Type *dummy_open_printer (void)
  324. {
  325.    slrn_error ("Printer not supported");
  326.    return NULL;
  327. }
  328.  
  329. static int dummy_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len)
  330. {
  331.    return -1;
  332. }
  333.  
  334. int dummy_close_printer (Slrn_Print_Type *p)
  335. {
  336.    return -1;
  337. }
  338.  
  339. /*}}}*/
  340. #endif                       /* USE_DUMMY_PRINT_CODE */
  341.  
  342.  
  343. int slrn_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len)
  344. {
  345.    char *b, *bmax;
  346.  
  347.    /* Map \n to \r\n */
  348.    b = buf;
  349.    bmax = b + len;
  350.     
  351.    while (b < bmax)
  352.      {
  353.     if (*b != '\n') 
  354.       {
  355.          b++;
  356.          continue;
  357.       }
  358.     
  359.     len = (unsigned int) (b - buf);
  360.     if (len)
  361.       {
  362.          if (*(b - 1) == '\r')
  363.            {
  364.           b++;
  365.           continue;
  366.            }
  367.          
  368.          if (-1 == write_to_printer (p, buf, len))
  369.            return -1;
  370.       }
  371.     
  372.     if (-1 == write_to_printer (p, "\r\n", 2))
  373.       return -1;
  374.     
  375.     b++;
  376.     buf =